//
//  StringExt.swift
//  kano
//
//  Created by Sophia on 2024/8/14.
//

import Foundation
import UIKit
import CryptoSwift

extension String {
    
    var verifyEmail: Bool { executePredicate(regex: "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$") }
    
    var verifyPhone: Bool { executePredicate(regex: "^0[0-9]{10}") }
    
    var verifyPwd: Bool { executePredicate(regex: "^([a-zA-Z0-9]{4}|[a-zA-Z0-9]{6})$")}
    
    var verifyName: Bool { executePredicate(regex: "^[a-zA-Z]+$")}

    var verifyBvn: Bool { executePredicate(regex: "^\\d{11}$")}
    
    var verifyPwdInput: Bool { executePredicate(regex: "^[a-zA-Z0-9]+$")}
    //^(?![0-9]+$)[0-9A-Za-z ]+$
    var verifyAddress: Bool { executePredicate(regex: "^(?![0-9]+$)[\\s\\S]+$")}

    
    var verifyWhatsApp: Bool { executePredicate(regex: "^0[0-9]{10}") }
    var verifyFacebook: Bool { executePredicate(regex: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$") || executePredicate(regex: "^0[0-9]{10}") }

    /// NSPredicate
    func executePredicate(regex: String) -> Bool {
        NSPredicate(format: "SELF MATCHES %@", regex).evaluate(with: self)
    }
    
    func insertSpaces(every n: Int, in str: String) -> String {
        let pattern = "(.{\(n)})(?=.)"
        let regex = try! NSRegularExpression(pattern: pattern, options: [])
        
        let modifiedString = regex.stringByReplacingMatches(
            in: str,
            options: [],
            range: NSRange(str.startIndex..., in: str),
            withTemplate: "$1 "
        )
        return modifiedString
    }
    //清理任何非数字字符
    func cleanedNumber() -> String {
        let pattern = "\\D"
        guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { return self }
        let range = NSRange(location: 0, length: self.utf16.count)
        let cleanedNumber = regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: "")
        return cleanedNumber
    }
    mutating func correctNumber() -> String {
        if self.hasPrefix("234") {
            self = String(self.dropFirst(3))
        }
        if self.count == 10, !self.hasPrefix("0") {
            let correntStr = "0\(self)"
            return correntStr
        }
        return self
    }
}

extension Optional where Wrapped == String {
    var isBlank : Bool {
        return self?.isBlank ?? true
    }
}

extension String {
    //掩码
    var maskedNumber: String {
            guard self.count >= 11 else { return self }
            let prefix = self.prefix(3)
            let suffix = self.suffix(4)
            let maskedNumber = "\(prefix)****\(suffix)"
            return maskedNumber
        }
    
    func ka_emojiStr() -> String {
        let var_scanner = Scanner(string: self)
        var var_value: UInt32 = 0
        var_scanner.scanHexInt32(&var_value)
        let var_charCode = Character(UnicodeScalar(var_value)!)

        return "\(var_charCode)"
    }
    
    subscript(index:Int) -> String {
        get{
            return String(self[self.index(self.startIndex, offsetBy: index)])
        }
        set{
            let tmp = self
            self = ""
            for (idx, item) in tmp.enumerated() {
                if idx == index {
                    self += "\(newValue)"
                }else{
                    self += "\(item)"
                }
            }
        }
    }
    
    var isBlank : Bool {
        return allSatisfy({ $0.isWhitespace}) || self.count == 0
    }
    
    var removeAllSpace: String {
        return self.replacingOccurrences(of: " ", with: "", options: .literal, range: nil)
    }
    
    mutating func insert(_ str: String, atIndex: Int) {
        if atIndex > count { return }
        let index = index(startIndex, offsetBy: atIndex)
        insert(contentsOf: str, at: index)
    }
    
    func subString(start:Int, length:Int = -1) -> String {
        var len = length
        if len == -1 {
            len = self.count - start
        }
        let st = self.index(startIndex, offsetBy:start)
        let en = self.index(st, offsetBy:len)
        return String(self[st ..< en])
    }
    
    /// string ->  Base64 str
    func toBase64() -> String {
        guard let data = self.data(using: .utf8) else { return "" }
        return data.base64EncodedString().toSafeBase64()!
    }
    
    func toBase64Data() -> Data {
        guard let data = self.data(using: .utf8) else { return Data() }
        return data
    }
    
    /// Base64 str -> string
    func fromBase64() -> String? {
        guard let data = Data(base64Encoded: self) else { return nil }
        return String(data: data, encoding: .utf8)
    }
    
    func toSafeBase64() -> String? {
        let safeBase64String = self
            .replacingOccurrences(of: "+", with: "-")
            .replacingOccurrences(of: "/", with: "_")
            .replacingOccurrences(of: "=", with: "")
        
        return safeBase64String
    }
    

    /// string -> json object
    func toJsonObject() -> Any? {
        guard let jsonData = self.data(using: .utf8) else { return nil }
        do {
            let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: [])
            return jsonObject
        } catch {
            print("Error parsing JSON Data: \(error.localizedDescription)")
            return nil
        }
    }
    
    func encodeUrl() -> String {
        let str = "U\(self)M"
        guard let data = str.data(using: .utf8) else {
            return ""
        }
        let base64Str = data.base64EncodedString()
        var encodedString = "hQhyZ" + base64Str
        encodedString = encodedString.replacingOccurrences(of: "+", with: "-")
        encodedString = encodedString.replacingOccurrences(of: "/", with: "_")
        encodedString = encodedString.trimmingCharacters(in: CharacterSet(charactersIn: "="))
        return encodedString
    }
    
    func isHexString() -> Bool {
        guard !self.isEmpty else { return false }
        let hexRegex = "^(0x)?([0-9A-Fa-f]+)$"
        let predicate = NSPredicate(format: "SELF MATCHES %@", hexRegex)
        return predicate.evaluate(with: self.lowercased())
    }
    
    func nsRange(of substring: String) -> NSRange {
        let nsString = self as NSString
        let range = nsString.range(of: substring)
        return range
    }
    
    
    func htmlToAttributedString() -> NSAttributedString? {
        guard let data = self.data(using: .utf8) else { return nil }
        
        do {
            return try NSAttributedString(
                data: data,
                options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue],
                documentAttributes: nil
            )
        } catch {
            print("Error converting HTML to NSAttributedString:", error)
            return nil
        }
    }


}
